﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.DirectoryServices;
using System.IO;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
using System.Management;
using System.Management.Automation.Host;
using System.Xml;
using System.DirectoryServices.ActiveDirectory;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Threading;
using System.Net;
using System.Text;
using System.Collections.ObjectModel;

namespace Main
{
    public class ControlLiveIDs
    {
        public class Model
        {
            public class WindowsLiveID
            {
                private String _liveID;
                private String _livePW;
                private int _id;

                public WindowsLiveID()
                {

                }

                public int Id
                {
                    get { return _id; }
                    set { _id = value; }
                }
                public String LiveID
                {
                    get { return _liveID; }
                    set { _liveID = value; }
                }
                public String LivePW
                {
                    get { return _livePW; }
                    set { _livePW = value; }
                }
            }
        }

        public class Control
        {
            ControlCommon common = new ControlCommon();
            
            /// <summary>
            /// saves Office365-enabled WindowsLiveID on SQL Azure
            /// </summary>
            /// <param name="liveID"></param>
            /// <param name="livePW"></param>
            /// <returns></returns>
            public String CreateWindowsLiveId(string liveID, string livePW, string companyName)
            {
                try
                {
                    common.CreateLog("Starting saving of New LiveID on SQL Azure for: " + liveID);
                    TechnoStoreMainDataContext db = new TechnoStoreMainDataContext();
                    WindowsLiveID live = new WindowsLiveID();
                    live.WL_ID = liveID;
                    live.WL_Password = livePW;
                    live.Company = companyName;
                    VerifiedDomain domain = new VerifiedDomain();
                    domain.DomainName = liveID.Substring(liveID.IndexOf('@') + 1);
                    domain.Company = companyName;
                    db.WindowsLiveIDs.InsertOnSubmit(live);
                    db.VerifiedDomains.InsertOnSubmit(domain);
                    db.SubmitChanges();
                    db.Dispose();

                    SetInfoAccount(liveID,livePW,companyName);
                    common.CreateLog("Stopping Successful saving of New LiveID on SQL Azure for: " + liveID);
                    return String.Empty;
                }
                catch (Exception e)
                {
                    common.CreateLog(e.ToString()); 
                    return e.ToString();
                }
            }

            /// <summary>
            /// gets existing Office365-enabled WindowsLiveIDs from SQL Azure if any
            /// </summary>
            /// <returns></returns>
            public List<WindowsLiveID> ViewLiveID(string companyName)
            {
                TechnoStoreMainDataContext db = new TechnoStoreMainDataContext();
                var query = from u in db.WindowsLiveIDs
                            orderby u.WL_ID ascending
                            where u.WL_ID != String.Empty && u.Company == companyName
                            select u;

                return query.ToList();
            }

            /// <summary>
            /// deletes existing Office365-enabled WindowsLiveIDs from SQL Azure
            /// </summary>
            /// <returns></returns>
            public String DeleteWindowsLiveId(string companyName)
            {
                try
                {
                    common.CreateLog("Starting deletion of LiveID from SQL Azure");
                    TechnoStoreMainDataContext db = new TechnoStoreMainDataContext();
                    var ids = from u in db.WindowsLiveIDs
                              where u.WL_ID != String.Empty && u.Company == companyName
                              select u;
                    foreach (var deleteID in ids)
                        db.WindowsLiveIDs.DeleteOnSubmit(deleteID);
                    db.SubmitChanges();
                    db.Dispose();

                    common.CreateLog("Stopping Successful deletion of LiveID from SQL Azure"); 
                    return String.Empty;
                }
                catch(Exception e)
                {
                    common.CreateLog(e.ToString()); 
                    return e.ToString();
                }
            }

            /// <summary>
            /// creates INFO user on SQL Azure to be used when sending e-mails
            /// </summary>
            /// <param name="credentialID"></param>
            /// <param name="credentialPW"></param>
            /// <param name="companyName"></param>
            /// <returns></returns>
            private Boolean SetInfoAccount(string credentialID, string credentialPW, string companyName)
            {
                try
                {
                    common.CreateLog("Starting setting info account on SQL Azure  for: " + credentialID);

                    string displayName = "INFO";
                    string userName = "info";
                    string email = userName + "@" + credentialID.Substring(credentialID.IndexOf('@') + 1);
                    string userPrincipalName = email;
                    string password = "Passw0rd@zure101";

                    TechnoStoreMainDataContext db = new TechnoStoreMainDataContext();
                    User user = new User();
                    user.name = "TECHNOSTORE";
                    user.surname = "INFO";
                    user.username = userName;
                    user.password = password;
                    user.email = email;
                    user.personalemail = email;
                    user.company = companyName;
                    user.isadmin = true;
                    user.changepassword = false;
                    db.Users.InsertOnSubmit(user);
                    db.SubmitChanges();

                    var query = from u in db.Users
                                where u.username == user.username && u.company == user.company
                                select new { u.ID };
                    int id = query.SingleOrDefault().ID;

                    if (id != -1)
                    {
                        Boolean pass365 = false;

                        if (SetInfoAccountOn365(credentialID, credentialPW, userPrincipalName, displayName, password))
                            pass365 = true;

                        if (pass365)
                        {
                            common.CreateLog("Stopping successful setting info account on SQL Azure for: " + credentialID);
                            return true;
                        }
                        else
                        {
                            db.Users.DeleteOnSubmit(db.Users.Where(u => u.ID == id && u.company == companyName).SingleOrDefault());
                            db.SubmitChanges();
                            common.CreateLog("Stopping unsuccessful setting info account O365 for: " + credentialID + " record deleted from SQL Azure");
                            return false;
                        }
                    }
                    else
                    {
                        common.CreateLog("Stopping unsuccessful setting info account on SQL Azure for: " + credentialID);
                        return false;
                    }
                }
                catch (Exception e)
                {
                    common.CreateLog("Stopping unsuccessful setting info account for: " + credentialID + " and the error is: " + e.ToString());
                    return false;
                }
            }

            /// <summary>
            /// creates INFO user on O365 to be used when sending e-mails
            /// </summary>
            /// <param name="credentialID"></param>
            /// <param name="credentialPW"></param>
            /// <param name="userPrincipalName"></param>
            /// <param name="displayName"></param>
            /// <param name="password"></param>
            /// <returns></returns>
            private Boolean SetInfoAccountOn365(string credentialID, string credentialPW, string userPrincipalName, string displayName, string password)
            {
                try
                {
                    common.CreateLog("Starting setting info account on O365 for: " + credentialID);

                    
                    ControlUsers.Control control = new ControlUsers.Control();
                    string planType = control.GetO365PlanType(credentialID, credentialPW);

                    string[] psScript = { @"$pass = convertto-securestring -asplaintext """ + credentialPW + @""" -force",
                                    @"$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist """ + credentialID + @""", $pass",
                                    @"Import-Module MSOnline",
                                    @"Connect-MsolService -Credential $credential",
                                    @"New-MsolUser -UserPrincipalName " + userPrincipalName + @" -DisplayName """ + displayName + @""" -FirstName ""TECHNOSTORE"" -LastName ""INFO"" -LicenseAssignment """ + planType + @""" -Password """ + password + @""" -PasswordNeverExpires $true -ForceChangePassword $false -UsageLocation ""US""",
                                    ""};
                    if (File.Exists(common.getPath("scriptSetInfo.ps1")))
                        File.Delete(common.getPath("scriptSetInfo.ps1"));
                    System.IO.File.WriteAllLines(common.getPath("scriptSetInfo.ps1"), psScript);
                    RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
                    Runspace myRunspace = RunspaceFactory.CreateRunspace(rsConfig);
                    myRunspace.Open();
                    Command command = new Command(common.getPath("scriptSetInfo.ps1"));
                    Pipeline pipeline = myRunspace.CreatePipeline();
                    pipeline.Commands.Add(command);
                    StringBuilder stringBuilder = new StringBuilder();
                    Collection<PSObject> results = pipeline.Invoke();
                    // check for errors (non-terminating) 
                    if (pipeline.Error.Count > 0)
                    {
                        //iterate over Error PipeLine until end 
                        while (!pipeline.Error.EndOfPipeline)
                        {
                            //read one PSObject off the pipeline 
                            var value = pipeline.Error.Read() as PSObject;
                            if (value != null)
                            {
                                //get the ErrorRecord 
                                var r = value.BaseObject as ErrorRecord;
                                if (r != null)
                                {
                                    //build whatever kind of message your want 
                                    stringBuilder.AppendLine(r.InvocationInfo.MyCommand.Name + " : " + r.Exception.Message);
                                    stringBuilder.AppendLine(r.InvocationInfo.PositionMessage);
                                    stringBuilder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo));
                                    stringBuilder.AppendLine(
                                    string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId));
                                }
                            }
                        }
                        common.CreateLog("Stopping unsuccessful setting info account on O365 for: " + credentialID + " with the error: " + stringBuilder.ToString());
                    }
                    common.CreateLog("Stopping successful setting info account on O365 for: " + credentialID);
                    return true;
                }
                catch (Exception e)
                {
                    common.CreateLog("Stopping unsuccessful setting info account on O365 for: " + credentialID + " and the error is: " + e.ToString());
                    return false;
                }
            }
        }
    }
}